iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Web 3

當 APP develop 遇上 web3 與 Metaverse 浪潮 系列 第 20

[Day 貳拾] 來開發元宇宙中藥鋪吧8- 載入時顯示 3D 牌匾

  • 分享至 

  • xImage
  •  

將 招牌 加入新的 Canvas

import React, { Suspense, useRef, useState } from 'react'

import { Canvas, useFrame, applyProps } from '@react-three/fiber'
import * as THREE from 'three'
import { useLayoutEffect } from 'react'
import { AccumulativeShadows, RandomizedLight, OrbitControls, Environment, useGLTF } from '@react-three/drei'
import { FlakesTexture } from 'three-stdlib'

function Box(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref = useRef()
  const ref_spotLight = useRef()

  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => {
    // ref.current.rotation.z += delta
    ref.current.rotation.x = -0.2
    ref.current.rotation.z = 0
    ref.current.position.x = 0
    ref.current.position.y = 2
  })
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={(event) => click(!clicked)}
      onPointerOver={(event) => hover(true)}
      onPointerOut={(event) => hover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
      <Suspense fallback={null}>
        <GoldenLogo position={[0, 0, -1]} scale={1.5} rotation={[0, Math.PI / 2, Math.PI / 2]} castShadow receiveShadow />
      </Suspense>
    </mesh>
  )
}

function CBLight(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref_spotLight = useRef()

  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)

  const [r] = useState(() => Math.random() * 10000)
  useFrame((_) => (ref_spotLight.current.position.x = -1.75 + Math.sin(_.clock.elapsedTime + r) * 175))
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh {...props} ref={ref_spotLight}>
      <spotLight angle={1} penumbra={0.5} intensity={0.75} position={[0, 15, 450]} castShadow />
    </mesh>
  )
}

export default function Logo() {
  return (
    <Canvas shadows camera={{ position: [0, 2, 10], fov: 25 }}>
      <Environment preset="city" />
      <color attach="background" args={['#FCF4EE']} />
      <ambientLight intensity={0.5} />
      <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
      <pointLight position={[-10, -10, -10]} />
      <pointLight castShadow position={[0, 1, 3]} penumbra={10} />
      <Suspense fallback={null}>
        <CBLight position={[0, 5, 50]} />
        <Box position={[0, 0, 0]} />
      </Suspense>
    </Canvas>
  )
}

export function GoldenLogo(props) {
  const { scene, materials } = useGLTF('/元藥堂.gltf')
  useLayoutEffect(() => {
    scene.traverse((obj) => obj.isMesh && (obj.receiveShadow = obj.castShadow = true))
    applyProps(materials.Golden, {
      color: 'orange',
      roughness: 0,
      normalMap: new THREE.CanvasTexture(new FlakesTexture(), THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping),
      'normalMap-repeat': [40, 40],
      normalScale: [0.05, 0.05]
    })
    applyProps(materials.TexTboxBase, {
      color: '#1C1F1E',
      roughness: 0,
      normalMap: new THREE.CanvasTexture(new FlakesTexture(), THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping),
      'normalMap-repeat': [40, 40],
      normalScale: [0.05, 0.05]
    })
  })
  return <primitive object={scene} {...props} />
}

接下來修改背景與照招牌照明的燈光效果

import React, { Suspense, useRef, useState } from 'react'

import { Canvas, useFrame, applyProps } from '@react-three/fiber'
// import GoldenText from './GoldenText'
// import { OrbitControls, Bounds, BakeShadows, Environment, ContactShadows } from '@react-three/drei'
import * as THREE from 'three'
import { useLayoutEffect } from 'react'
import { AccumulativeShadows, RandomizedLight, OrbitControls, Environment, useGLTF } from '@react-three/drei'
import { FlakesTexture } from 'three-stdlib'

function Box(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref = useRef()
  const ref_spotLight = useRef()

  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => {
    // ref.current.rotation.z += delta
    ref.current.rotation.x = -0.2
    ref.current.rotation.z = 0
    ref.current.position.x = 0
    ref.current.position.y = 2
  })
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={(event) => click(!clicked)}
      onPointerOver={(event) => hover(true)}
      onPointerOut={(event) => hover(false)}>
      {/* <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} /> */}
      <Suspense fallback={null}>
        {/* <GoldenLogo position={[0, 0, -1]} scale={1.5} rotation={[0, Math.PI / 2, Math.PI / 2]} castShadow receiveShadow /> */}
        <GoldenLogo position={[0, 0, -1]} scale={1.5} rotation={[0, Math.PI / 2, Math.PI / 2]} castShadow receiveShadow />
      </Suspense>
    </mesh>
  )
}

function CBLight(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref_spotLight = useRef()

  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  // useFrame((state, delta) => {
  //   // ref.current.rotation.z += delta
  //   // ref.current.rotation.x = -0.2
  //   // ref.current.rotation.z = 0
  //   // ref.current.position.x = 0
  //   ref_spotLight.current.position.x += delta * 10
  // })
  const [r] = useState(() => Math.random() * 10000)
  useFrame((_) => (ref_spotLight.current.position.x = -1.75 + Math.sin(_.clock.elapsedTime + r) * 175))
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh {...props} ref={ref_spotLight}>
      <spotLight angle={1} penumbra={0.5} intensity={0.75} position={[0, 15, 450]} castShadow />
    </mesh>
  )
}

export default function Logo() {
  return (
    <Canvas shadows camera={{ position: [0, 2, 10], fov: 25 }}>
      {/* sunset: string;
    dawn: string;
    night: string;
    warehouse: string;
    forest: string;
    apartment: string;
    studio: string;
    city: string;
    park: string;
    lobby: string; */}
      <Environment preset="night" />
      {/* <color attach="background" args={['#FCF4EE']} /> */}
      {/* <ambientLight intensity={1} /> */}
      <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
      <pointLight position={[-10, -10, -10]} />
      <pointLight castShadow position={[0, 1, 3]} penumbra={10} />
      <Suspense fallback={null}>
        <CBLight position={[0, 5, 50]} />
        <Box position={[0, 0, 0]} />
      </Suspense>
      {/* <Suspense fallback={null}>
        <GoldenText position={[0, 2, 0]} scale={1.5} rotation={[0, Math.PI / 2, Math.PI / 2]} castShadow receiveShadow />
      </Suspense> */}
    </Canvas>
  )
}

export function GoldenLogo(props) {
  const { scene, materials } = useGLTF('/元藥堂.gltf')
  // const { scene, materials } = useGLTF('https://market-assets.fra1.cdn.digitaloceanspaces.com/market-assets/models/suzanne-high-poly/model.gltf')
  useLayoutEffect(() => {
    scene.traverse((obj) => obj.isMesh && (obj.receiveShadow = obj.castShadow = true))
    applyProps(materials.Golden, {
      color: 'orange',
      roughness: 0,
      normalMap: new THREE.CanvasTexture(new FlakesTexture(), THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping),
      'normalMap-repeat': [40, 40],
      normalScale: [0.05, 0.05]
    })
    applyProps(materials.TexTboxBase, {
      color: '#1C1F1E',
      roughness: 0,
      normalMap: new THREE.CanvasTexture(new FlakesTexture(), THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping),
      'normalMap-repeat': [40, 40],
      normalScale: [0.05, 0.05]
    })

    // applyProps(materials.insideBase, {
    //   color: 'FFBD33',
    //   roughness: 0,
    //   normalMap: new THREE.CanvasTexture(new FlakesTexture(), THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping),
    //   'normalMap-repeat': [40, 40],
    //   normalScale: [0.05, 0.05]
    // })
  })
  return <primitive object={scene} {...props} />
}


上一篇
[Day 拾玖] 來開發元宇宙中藥鋪吧7- 載入畫面
下一篇
[Day 貳拾壹] 來開發元宇宙中藥鋪吧9 - 修正載入時 3D 牌匾 與場景中牌匾衝突
系列文
當 APP develop 遇上 web3 與 Metaverse 浪潮 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
ddyme
iT邦新手 4 級 ‧ 2022-10-04 22:58:03

笑死 好可愛

我要留言

立即登入留言